import { ExternalLink } from 'lucide-react'; import type { Metadata } from 'next'; import Link from 'next/link'; import { notFound } from 'next/navigation'; import { SensorTierBadge, SignificanceBadge, StatusBadge } from '@/components/ui/badges'; import { KV, Row } from '@/components/ui/key-value'; import { LiveAgo } from '@/components/ui/live'; import { Container, Empty, Note, Stat, StatGrid } from '@/components/ui/section'; import { api, ApiError, safe } from '@/lib/api'; import { fmtDateTime, fmtDuration, fmtInt, fmtScore } from '@/lib/format'; import { routes, SENSOR_TIER_LABELS, SURFACE_LABELS } from '@/lib/site'; export const revalidate = 60; export const metadata: Metadata = { title: 'Sensor', robots: { index: false } }; export default async function SensorPage({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; let s; try { s = await api.sensor(id); } catch (e) { if (e instanceof ApiError && e.notFound) notFound(); throw e; } const [snaps, changes] = await Promise.all([safe(api.sensorSnapshots(id, 50)), safe(api.sensorChanges(id, 50))]); const stale = s.last_success_at && Date.now() - new Date(s.last_success_at).getTime() > 2 * 86_400_000; return (

Sensor

{s.company.display_name} {' '} · {SURFACE_LABELS[s.surface] ?? s.surface}

{s.url}

{stale && (

Last successfully checked {s.last_failure_class ? ` — recent failures: ${s.last_failure_class} (${s.consecutive_failures} consecutive)` : ''}.

)}

Snapshot versions

{!snaps ? ( ) : snaps.items.length === 0 ? ( No snapshot stored yet for this sensor. ) : (
{snaps.items.map((v, i) => { const prev = snaps.items[i + 1]; return ( ); })}
v Fetched Title Blocks Text Hash Diff
{v.version_no} {fmtDateTime(v.fetched_at)} {v.title ?? '—'} {fmtInt(v.block_count)} {fmtInt(v.text_length)} {v.content_hash.replace('sha256:', '').slice(0, 10)} {prev ? vs v{prev.version_no} : first}
)}

Detected changes

{!changes ? ( ) : changes.items.length === 0 ? ( No change detected yet. ) : (
    {changes.items.map((c) => (
  • {fmtDateTime(c.detected_at)} +{c.blocks_added} · −{c.blocks_removed} · ~{c.blocks_modified} {c.kind}
  • ))}
)}
); }